package yunjiao.javatutorials.guava.concurrent;

import com.google.common.util.concurrent.Striped;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;

/**
 * 带超时的锁示例
 *
 * @author yangyunjiao
 */
public class StripedLockWithTimeout {
    private static final Striped<Lock> STRIPED_LOCK = Striped.lock(32);
    private static final long TIMEOUT_MS = 1000;

    public static boolean tryUpdateWithTimeout(String resourceId, String newValue) {
        Lock lock = STRIPED_LOCK.get(resourceId);
        try {
            if (lock.tryLock(TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
                try {
                    // 执行需要同步的操作
                    System.out.println(Thread.currentThread().getName() + " 更新资源: " + resourceId + " 值为: " + newValue);
                    Thread.sleep(500); // 模拟操作
                    return true;
                } finally {
                    lock.unlock();
                }
            } else {
                System.out.println(Thread.currentThread().getName() + " 获取锁超时: " + resourceId);
                return false;
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return false;
        }
    }

    public static void main(String[] args) throws InterruptedException {
        int threadNum = 17;
        ExecutorService executor = Executors.newFixedThreadPool(10);
        CountDownLatch latch = new CountDownLatch(threadNum);

        // 模拟并发转账
        for (int i = 0; i < threadNum; i++) {
            final int index = i;
            executor.submit(() -> {
                try {
                    tryUpdateWithTimeout("resource_1", "value_" + index);
                    tryUpdateWithTimeout("resource_2", "value_" + index);
                    tryUpdateWithTimeout("resource_3", "value_" + index);
                } finally {
                    latch.countDown();
                }
            });
        }

        latch.await();
        executor.shutdown();
    }
}
